#include "BondDetailBrokerBestPrice.h"
#include "BondDetailData.h"
#include "../BondUtility.h"
#include "../GridImage.h"
#include <uam/UserAccountManager.h>
#include <core/StyleMgr.h>
#include <widgets/STabCtrl.h>
#include <widgets/SComboBox.h>
#include <widgets/table/STable.h>
#include <widgets/table/STableColumnSet.h>
#include<qbtools/tools.h>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QLabel>
#include <QTimer>
#include <QtGlobal>
#include <QStylePainter>
#include <QTableView>
#include <QHeaderView>
#include "../BondColDelegate.h"

BrokerBestPrice::BrokerBestPrice(QWidget* p, QSharedPointer<DetailData> data)
	: QFrame(p), m_data(data)
{
	const char* qbLicense = SSUserAccountManager::instance().GetPermission().GetValue(USER_PERMISSION_QB_PRO);
	const char* qbBroker = SSUserAccountManager::instance().GetPermission().GetValue(USER_PERMISSION_BROKER_BESTQUOTE);
	m_showAll = ((strcmp(qbLicense, "0") == 0 && strcmp(qbBroker, "1") == 0) ||
		strcmp(qbLicense, "1") == 0 ||
		strcmp(qbLicense, "2") == 0);

	m_showTab = strcmp(qbLicense, "1") == 0 || strcmp(qbLicense, "0") == 0;
	m_showAllTable = strcmp(qbLicense, "1") == 0 || strcmp(qbLicense, "2") == 0;
	if (!m_showTab)//datafeed
		m_brokerId = 0; //全部

	QVBoxLayout* vl = new QVBoxLayout();
	vl->setContentsMargins(4, 4, 4, 4);
	vl->setSpacing(4);
	setLayout(vl);

	m_brokerTab = BondUtility::createBrokerTab(this, false);//不显示也生成，获取broker的数目
	if (m_brokerTab == nullptr)
		m_showTab = false;

	if (m_showTab)
	{
		m_brokerTab->setFixedHeight(24);
		m_brokerTab->selectTab(0);
		vl->addWidget(m_brokerTab);

		m_brokerId = m_brokerTab->tabData(0).toInt();
		connect(m_brokerTab, &STabCtrl::tabSelected, this, &BrokerBestPrice::onBrokerTabSelectChanged);
	}
    /*else*/ if (m_brokerTab)
		m_brokerTab->hide();

	QHBoxLayout* titleLayout = new QHBoxLayout();
	titleLayout->setContentsMargins(0, 0, 0, 0);
	titleLayout->setSpacing(4);
	vl->addLayout(titleLayout);

	titleLayout->addStretch();
	titleLayout->addWidget(new QLabel(tr("清算速度"), this));

	m_cbClearSpeed = new SComboBox(this);
	titleLayout->addWidget(m_cbClearSpeed);
	m_cbClearSpeed->setFixedSize(96, 24);
	QStringList speeds;
	speeds << tr("不限") << tr("T+0") << tr("T+1") << tr("远期") << tr("非远期");
	m_cbClearSpeed->addItems(speeds);
	connect(m_cbClearSpeed, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &BrokerBestPrice::onClearSpeedChanged);

	m_bestBidOfr = new BestBidOfr(this);
    m_bestBidOfr->setFixedHeight(40);//(m_showAllTable ? 40 : 60);
	vl->addWidget(m_bestBidOfr);

	m_bestTable = new SVirtualTable(this);
	if (!m_showAllTable)
	{
		m_bestTable->setFixedHeight(60);
        //m_bestTable->hide();
	}
	else
	{
		int brokerCount = m_brokerTab ? m_brokerTab->getTabCount() : 0;
		if (m_showAll)
			--brokerCount;

		m_bestTable->setFixedHeight((brokerCount + 1) * 26);//TODO:获取table的行高
	}

	vl->addWidget(m_bestTable);
	setFixedHeight(vl->sizeHint().height());

	initBestPriceList();
	connect(m_data.get(), &DetailData::brokerBestQuoteChanged, m_bestBidOfr, &BestBidOfr::onBrokerBestQuoteChanged);
	connect(m_data.get(), &DetailData::brokerBestPriceChanged, this, &BrokerBestPrice::onBestPriceChanged);
	connect(m_data.get(), &DetailData::bondChanged, this, &BrokerBestPrice::updateList);

	QString style = QString("BrokerBestPrice {background-color:#%1;border:none;border-radius:2px;}").arg(StyleMgr::instance().color("BasicPlate").rgb(), 0, 16);
	setStyleSheet(style);
}

void BrokerBestPrice::paintEvent(QPaintEvent* event)
{
	QFrame::paintEvent(event);

	QRect r = rect();
	r.setTop(m_cbClearSpeed->frameGeometry().top());
	r.setHeight(24);
	QStylePainter painter(this);
	painter.drawText(r, tr("报价"), QTextOption(Qt::AlignCenter));
}

void BrokerBestPrice::onBrokerTabSelectChanged(int index)
{
	m_brokerId = m_brokerTab->tabData(index).toInt();
	updateList();

	if (!m_showAllTable)
	{
		m_bestBidOfr->setVisible(m_brokerId == 0);
		m_bestTable->setVisible(m_brokerId > 0);
	}
}

void BrokerBestPrice::onClearSpeedChanged(int index)
{
	switch (index)
	{
	case 1:
		m_clearSpeed = 1;
		break;
	case 2:
		m_clearSpeed = 2;
		break;
	case 3:
		m_clearSpeed = 4;
		break;
	case 4:
		m_clearSpeed = 3;
		break;
	default:
		m_clearSpeed = 0;
		break;
	}

	m_data->setClearSpeed(m_clearSpeed);
	updateList();
}

void BrokerBestPrice::onBestPriceChanged(std::map<std::string, int> changes)
{
	updateList();
	for (auto bpChanage : changes)
	{
		FlashInfo fi;
		fi.id = QString::fromStdString(bpChanage.first);
		fi.entireRow = false;

		if ((bpChanage.second & 1) == 1)
		{
			fi.cols.push_back(1);
			fi.cols.push_back(2);
		}

		if ((bpChanage.second & 2) == 2)
		{
			fi.cols.push_back(3);
			fi.cols.push_back(4);
		}
		m_bestTable->addFlashInfo(fi);
	}
}

void BrokerBestPrice::initBestPriceList()
{
	DefaultTableModel* m = new DefaultTableModel(this);
	m->setTable(m_bestTable);
	m_bestTable->table()->setModel(m);

	m_tableSet = new STableColumnSet(m_bestTable,"BrokerBestPrice", this);
	m_tableSet->setTableWidthFixed(true);
	BEGIN_COLUMN;
    ADD_COLUMN(0, m_tableSet, "", 0, 50, 12, -1, false, (Qt::Alignment)(Qt::AlignVCenter | Qt::AlignLeft), kFixed, "");
	ADD_COLUMN(1, m_tableSet, "Vol.Bid", 0, -1, 12, 0.25, false, (Qt::Alignment)(Qt::AlignVCenter | Qt::AlignRight), kAuto, "");
	ADD_COLUMN(2, m_tableSet, "Bid", 0, -1, 12, 0.25, false, (Qt::Alignment)(Qt::AlignVCenter | Qt::AlignRight), kAuto, "");
	ADD_COLUMN(3, m_tableSet, "Ofr", 0, -1, 12, 0.25, false, (Qt::Alignment)(Qt::AlignVCenter | Qt::AlignRight), kAuto, "");
	ADD_COLUMN(4, m_tableSet, "Vol.Ofr", 0, -1, 12, 0.25, false, (Qt::Alignment)(Qt::AlignVCenter | Qt::AlignRight), kAuto, "");
	ADD_COLUMN(5, m_tableSet, tr("更新时间"), 0, 60, 12, -1, false, (Qt::Alignment)(Qt::AlignVCenter | Qt::AlignRight), kFixed, "");

    BrokerCorpDelegate* brokerCorpDelegate = new BrokerCorpDelegate(m_bestTable);
    m_bestTable->table()->setItemDelegateForColumn(0, brokerCorpDelegate);

    m_tableSet->apply();

	m_bestTable->table()->horizontalHeader()->show();
}

void BrokerBestPrice::update(int nBrokerId)
{
	m_brokerId = nBrokerId;

	int count = m_brokerTab->getTabCount();
	for (int i = 0; i < count; i++)
	{
		if (nBrokerId == m_brokerTab->tabData(i).toInt())
		{
			m_brokerTab->selectTab(i);
		}
	}
	
	updateList();

	if (!m_showAllTable)
	{
		m_bestBidOfr->setVisible(m_brokerId == 0);
		m_bestTable->setVisible(m_brokerId > 0);
	}
}
bool BrokerBestPrice::isShowTab()
{
	return m_showTab;
}


static std::vector<REPORT> getDealExListRptMap(bool disAll, int brokerId, const CBondInfo& bond, int clearSpeed)
{
	std::vector<REPORT> vctReport;
	const CBrokerList& brokerList = SSUserAccountManager::instance().GetReadonlyBroker();
	const std::vector<int>& vctBroker = brokerList.GetSortKey();
	const CBrokerList::BrokerMap& brokermap = brokerList.GetBrokerMap();
	CBrokerList::BrokerMap::const_iterator mit;
	char cBroker[8] = { 0 };
	for (auto itor = vctBroker.begin(); itor != vctBroker.end(); itor++) {
		mit = brokermap.find(*itor);
		if (mit == brokermap.end())	continue;
		const CBrokerUnit& bu = mit->second;
		if (!CBrokerList::IsValidBroker(bu.m_brokerID)) continue;
		if (!bu.m_enableFlag_BOND && !bu.m_enableFlag_NCD) continue;
		if(brokerId > 0 && brokerId != bu.m_brokerID)
			continue;

#ifdef _MSC_VER
		sprintf_s(cBroker, sizeof(cBroker), "%d", *itor);
#else
		snprintf(cBroker, sizeof(cBroker), "%d", *itor);
#endif
		REPORT rpt;
		bool getRpt = false;
		if (clearSpeed <= 0)
			getRpt = CBondContainer::instance().GetCompanyRepByKey(bond.GetCombBondKey(), cBroker, rpt);
		else
		{
			getRpt = CBondContainer::instance().GetCompanyRepByKeyAndSettlement(bond.GetCombBondKey(), cBroker, clearSpeed, rpt);
		}

		if (getRpt) {
			vctReport.push_back(rpt);
		}
		else if (disAll) {
			memset(&rpt, 0, sizeof(REPORT));
			FMTBUF(rpt.m_company_id, "%d", *itor);
			vctReport.push_back(rpt);
		}
	}
	return vctReport;
}

void BrokerBestPrice::updateList()
{
	std::vector<REPORT> reports = getDealExListRptMap(true, m_brokerId, m_data->bond(), m_clearSpeed);
	int count = reports.size();

	bool isRating = m_data->bond().IsRatingDebt();
	bool isExchange = m_data->bond().IsExchange();
	bool isDatafeed = (strcmp(SSUserAccountManager::instance().GetPermission().GetValue(USER_PERMISSION_QB_PRO), "2") == 0);
	bool isQMValid = (strcmp(SSUserAccountManager::instance().GetPermission().GetValue(USER_PERMISSION_NEW_QM), "1") == 0
		&& strcmp(SSUserAccountManager::instance().GetPermission().GetValue(USER_PERMISSION_QM_BROKER_CONTACT), "1") == 0);
	bool isQMMoveFront = (!isDatafeed && isQMValid);

	QFont f = font();
	f.setPixelSize(13);
	f.setBold(true);

	QFont timeF = f;
	timeF.setPixelSize(12);

	QStandardItemModel* model = dynamic_cast<QStandardItemModel*>(m_bestTable->table()->model());
	model->removeRows(0, model->rowCount());
	for (int row = 0; row < count; ++row)
	{
		const REPORT& report = reports[row];
		bool isBidValid = (strcmp(report.m_bidinfo.m_price_status, "0") != 0);
		bool isOfrValid = (strcmp(report.m_askinfo.m_price_status, "0") != 0);
		for (int col = 0; col < 6; ++col)
		{
			QStandardItem* item = new QStandardItem();
			model->setItem(row, col, item);
			item->setData((int)(Qt::AlignRight | Qt::AlignVCenter), Qt::TextAlignmentRole);
			item->setData(StyleMgr::instance().color("Highlight"), Qt::ForegroundRole);
			item->setData(StyleMgr::instance().color("BasicPlate"), Qt::BackgroundRole);
			item->setData(report.m_company_id, DataIdRole);
			item->setFont(f);

			if (col == 0)//中介图标
            {
                int nCurBroker = atoi(report.m_company_id);
                if (CBrokerList::IsValidBroker(nCurBroker)) {
                    item->setData(nCurBroker, BrokerIdRole);
                }
            }
            /*{
				item->setData((int)(Qt::AlignLeft | Qt::AlignVCenter), Qt::TextAlignmentRole);
                //if(!isDatafeed)
                //	continue;
				int nCuBroker = atoi(report.m_company_id);
				if (CBrokerList::IsValidBroker(nCuBroker)) {
					int nImg = -1;
					if (nCuBroker == 98)
						nImg = 27;
					else
						nImg = nCuBroker + 20;

					item->setData(BondUtility::gridImage((EnumImgFlag)nImg), Qt::DecorationRole);
				}
            }*/
			else if (col == 1) //买入量
			{
				BondUtility::DisplayVolumn(report.m_bidinfo, isBidValid, false, item);
			}
			else if (col == 2) //买入
			{
				BondUtility::DisplayPriceNew(report.m_bidinfo, isBidValid, StyleMgr::instance().color("Bid_GVN_H1"), false, false, false, false, m_clearSpeed > 0, item);
			}
			else if (col == 3) //卖出
			{
				BondUtility::DisplayPriceNew(report.m_askinfo, isOfrValid, StyleMgr::instance().color("Ofr_TKN_H1"), false, false, false, false, m_clearSpeed > 0, item);
			}
			else if (col == 4) //卖出量
			{
				BondUtility::DisplayVolumn(report.m_askinfo, isOfrValid, false, item);
			}
			else if (col == 5)//更新时间
			{
				time_t t_Current = 0;
				t_Current = qMax(report.m_time, report.m_create_time);
				BondUtility::SetUpdateTimeCol(item, t_Current);
				item->setData(timeF, Qt::FontRole);
			}
		}
	}
	
}

BestBidOfr::BestBidOfr(QWidget* p)
	: QWidget(p)
{
	m_timer = new QTimer(this);
	m_timer->callOnTimeout(this, &BestBidOfr::onTimeout);
}

void BestBidOfr::paintEvent(QPaintEvent* event)
{
	int centerX = rect().center().x();

    const int XSpacing = 8;
    const QSize bridgeSize{64, 28};
	
	QStylePainter painter(this);
	//绘制背景
	painter.setPen(Qt::NoPen);
	QColor bkClr = StyleMgr::instance().color("Bid_GVN_H3");
	if(m_bidFlashCount > 0 && m_bidFlashCount % 2 == 0)
		bkClr = StyleMgr::instance().color("Bid_GVN_H2");
	QRect bkRect = rect();
	bkRect.setRight(centerX);
	painter.setBrush(QBrush(bkClr));
	painter.drawRect(bkRect);

	bkClr = StyleMgr::instance().color("Ofr_TKN_H3");
	if (m_ofrFlashCount > 0 && m_ofrFlashCount % 2 == 0)
		bkClr = StyleMgr::instance().color("Ofr_TKN_H2");
	bkRect = rect();
	bkRect.setLeft(centerX);
	painter.setBrush(QBrush(bkClr));
	painter.drawRect(bkRect);

	//绘制文字
	QRect txtRect = rect();
    txtRect.setLeft(XSpacing);

    QPen penBid(StyleMgr::instance().color("Bid_GVN_H2"));
    painter.setPen(penBid);
    painter.drawText(txtRect, tr("最优Bid"), QTextOption(Qt::AlignLeft | Qt::AlignBottom));

    QPen penOfr(StyleMgr::instance().color("Ofr_TKN_H2"));
    painter.setPen(penOfr);
    int ofrX = rect().right() - XSpacing;
	txtRect.setRight(ofrX);
    painter.drawText(txtRect, tr("最优Ofr"), QTextOption(Qt::AlignRight | Qt::AlignBottom));

	//绘制价格
	QFont f = font();
	f.setBold(true);
	f.setPixelSize(22);
	painter.setFont(f);

    const int bidValueRight = centerX - XSpacing - bridgeSize.width()/2;
	txtRect = rect();
    txtRect.setRight(bidValueRight);
	painter.setPen(StyleMgr::instance().color("Bid_GVN_H1"));
	painter.drawText(txtRect, m_bidValue, QTextOption(Qt::AlignRight | Qt::AlignVCenter));

    QFontMetrics fm(f);
    const int bidValueTxtWidth = fm.horizontalAdvance(m_bidValue);

    if (m_bidType != emOther)
    {
        QPixmap img = BondUtility::gridImage(m_bidType == emCleanPrice ? grid_tag_netprice : grid_tag_fullprice);
        painter.drawPixmap(txtRect.right() - bidValueTxtWidth - 4 - img.width(), txtRect.center().y() - img.height() / 2, img);
    }

    const int ofrValueLeft = centerX + XSpacing + bridgeSize.width()/2;
	txtRect = rect();
    txtRect.setLeft(ofrValueLeft);

    const int ofrValueTxtWidth = fm.horizontalAdvance(m_ofrValue);

	if (m_ofrType != emOther)
	{
		QPixmap img = BondUtility::gridImage(m_ofrType == emCleanPrice ? grid_tag_netprice : grid_tag_fullprice);
		painter.drawPixmap(txtRect.left(), txtRect.center().y() - img.height() / 2, img);
		txtRect.setLeft(txtRect.left() + img.width() + 4);
	}
	painter.setPen(StyleMgr::instance().color("Ofr_TKN_H1"));
	painter.drawText(txtRect, m_ofrValue, QTextOption(Qt::AlignLeft | Qt::AlignVCenter));

    {
        //draw the m_bidVolume
        f.setPixelSize(12);
        painter.setFont(f);
        painter.setPen(StyleMgr::instance().color("ChartH8"));
        txtRect = rect();
        txtRect.setRight(bidValueRight - bidValueTxtWidth - XSpacing);
        painter.drawText(txtRect, m_bidVolume, QTextOption(Qt::AlignRight | Qt::AlignVCenter));

        //draw the m_ofrVolume
        txtRect = rect();
        txtRect.setLeft(ofrValueLeft + ofrValueTxtWidth + XSpacing);
        painter.drawText(txtRect, m_ofrVolume, QTextOption(Qt::AlignLeft | Qt::AlignVCenter));
    }

    //draw the bridge
    {
        const int bridgeBorder = 4;
        QRect bridgeRect;
        bridgeRect.setSize({ bridgeSize.width(), bridgeSize.height()});
        bridgeRect.moveCenter(rect().center());
        const QColor border = StyleMgr::instance().color("ElementBackground");
        const QColor bkg = StyleMgr::instance().color("StaticTextBK");
        const QColor txt = StyleMgr::instance().color("TitleWord");
        painter.fillRect(bridgeRect, border);

        bridgeRect.setSize({ bridgeSize.width()-bridgeBorder, bridgeSize.height()-bridgeBorder });
        bridgeRect.moveCenter(rect().center());
        painter.fillRect(bridgeRect, bkg);

        painter.setPen(txt);
        painter.drawText(bridgeRect, "??", QTextOption(Qt::AlignCenter));
    }
}

void BestBidOfr::onBrokerBestQuoteChanged(xQBBestPriceSynthetical_Unit_c bid, xQBBestPriceSynthetical_Unit_c ofr, bool canFlash)
{
	auto fnPrice = [&](const xQBBestPriceSynthetical_Unit_c& v)->QString {
		//m_bp_status为原m_deal_status, 订单状态,  -1-待审核；0-发布；1-成交；2-作废
		if (strcmp(v.m_bp_status, "0") != 0) {
			return "--";
		}
		QString tmp = SSTools::FormatePrice(v.m_price);
		return tmp.isEmpty() ? "--" : tmp;
	};
	auto fnQuoteType = [&](const xQBBestPriceSynthetical_Unit_c& v)->int {
		//m_quotetype 报价类型，0-有意向；1-净价；2-全价；3-收益率；4-利差
		if (strcmp(v.m_quotetype, "1") == 0) {
			return emCleanPrice;
		}
		else if (strcmp(v.m_quotetype, "2") == 0) {
			return emFullPrice;
		}
		else {
			return emOther;
		}
	};
	auto fnIsIntentionalPrice = [&](const xQBBestPriceSynthetical_Unit_c& v)->bool {
		//判断是否意向价
		return strcmp(v.m_quotetype, "0") == 0;
	};
    auto fnVolume = [&](const xQBBestPriceSynthetical_Unit_c& v)->QString {
        //use v.m_volume ?
        return "??";
    };

	QString newBidValue = fnIsIntentionalPrice(bid) ? "Bid" : fnPrice(bid);
	int newBidType = fnQuoteType(bid);

	QString newOfrValue = fnIsIntentionalPrice(ofr) ? "Ofr" : fnPrice(ofr);
	int newOfrType = fnQuoteType(ofr);

    m_bidVolume = fnVolume(bid);
    m_ofrVolume = fnVolume(ofr);

	if (newBidValue != m_bidValue || newBidType != m_bidType)
	{
		m_bidValue = newBidValue;
		m_bidType = newBidType;
		if (canFlash)
			m_bidFlashCount = 10;
		else
			m_bidFlashCount = 0;
	}

	if (newOfrValue != m_ofrValue || newOfrType != m_ofrType)
	{
		m_ofrValue = newOfrValue;
		m_ofrType = newOfrType;
		if (canFlash)
			m_ofrFlashCount = 10;
		else
			m_ofrFlashCount = 0;
	}
	if (m_bidFlashCount == 10 || m_ofrFlashCount == 10)
		m_timer->start(400);
	else
		m_timer->stop();

	update();
}

void BestBidOfr::onTimeout()
{
	if (m_bidFlashCount <= 0 && m_ofrFlashCount <= 0)
		m_timer->stop();
	
	if (m_bidFlashCount > 0)
		--m_bidFlashCount;
	if (m_ofrFlashCount > 0)
		--m_ofrFlashCount;

	update();
}
